<!DOCTYPE html>

<html>
<head>
    <meta charset="UTF-8">
    <title>响应式</title>
</head>
<body>

    <div class="wrapper">
        <input type="text">
        <p class="info"></p>
    </div>

    <script type="text/javascript">
        const input = document.querySelector('.wrapper>input');
        const info = document.querySelector( '.wrapper>.info' );

        let render = function( source ){
            input.value = source.message ;
            info.innerHTML = source.message ;
        }

        function reactive( source ){
            // 创建一个纯对象(不继承任何对象也没有原型和构造)
            const pure = Object.create(null);

            // 获取 source 实例中所有自有属性名称组成的数组
            const propertyNames = Object.getOwnPropertyNames( source );

            // 通过 Array.prototype.forEach 函数来遍历数组
            propertyNames.forEach( propertyName => {
                // 属性描述符
                let descriptor = {
                    configurable: true,
                    enumerable: true,
                    get(){
                        console.log( `get ${propertyName}` );
                        // 获取 source 实例属性的值(用变量propertyName确定属性名称)
                        return source[ propertyName ];
                    },
                    set( value ){
                        console.log( `set ${propertyName} : ${ value }` );
                        // 为 source 实例属性赋值值(用变量propertyName确定属性名称)
                        source[ propertyName ] = value ;
                        // 调用 render 函数修改页面上显示的内容
                        render( source );
                    }
                }
                // 为 pure 定义一个实例属性( 名称通过 propertyName 变量来确定 )
                Object.defineProperty( pure , propertyName , descriptor );
            });
            
            // 最后返回 pure 实例
            return pure;
        }

        const origin = {
            message: ''
        }

        const user = reactive( origin );

        let listener = evt => {
            console.log( '新输入的字符: ' , evt.data );
            let content = evt.target.value ; // let content = input.value
            console.log( content );
            // 通过 user 实例的 `set message` 赋值
            user.message = content ;
        }
        // 监听输入框中的 input 事件
        input.addEventListener( 'input', listener, false );
    </script>
    
</body>
</html>